---
title: "Sidebar"
description: A collapsible panel for navigation or additional content, typically positioned on the side of the screen.
order: 1
published: true
references: ["https://react-spectrum.adobe.com/react-aria/Link.html#props", "https://react-spectrum.adobe.com/react-aria/Disclosure.html#props"]
---

## Basic
The sidebar is a versatile component designed to organize your site's content and navigation. It offers a structured overview of your site's layout, making it easier for users to explore and locate information.
<Sandbox
  registries={[
    "sidebar-01",
  ]}
/>

## Installation
```bash
npx shadcn@latest add @intentui/sidebar
```

## Composed components
<Composed components={['tooltip', 'sheet', 'link', 'button']} />

## Manual installation
```bash
npm i react-aria-components @heroicons/react tailwind-merge
```
<SourceCode toShow={'sidebar'}/>

## CSS Variables
The sidebar just need one base color to work, the accent will generate from the base and the primary color just taking from the primary color you have. Make sure you have set evertyhing up, or hover into [theme page](/themes) to see the bunch of colors you can get. Too lazy? just copy the default color below to your stylesheet.
```
@theme inline {
  --color-sidebar: var(--sidebar);
  --color-sidebar-fg: var(--sidebar-fg);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-primary-fg: var(--sidebar-primary-fg);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-accent-fg: var(--sidebar-accent-fg);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-ring: var(--sidebar-ring);
}

:root {
  --sidebar: oklch(0.985 0 0);
  --sidebar-fg: oklch(0.141 0.005 285.823);
  --sidebar-primary: oklch(0.623 0.214 259.815 / 0.15);
  --sidebar-primary-fg: oklch(0.488 0.243 264.376);
  --sidebar-accent: oklch(0.92 0.004 286.32);
  --sidebar-accent-fg: oklch(0.141 0.005 285.823);
  --sidebar-border: oklch(0.901 0.006 286.286);
  --sidebar-ring: oklch(0.546 0.245 262.881);
}

.dark {
  --sidebar: oklch(0.21 0.006 285.885);
  --sidebar-fg: oklch(0.985 0 0);
  --sidebar-primary: oklch(0.623 0.214 259.815 / 0.1);
  --sidebar-primary-fg: oklch(0.707 0.165 254.624);
  --sidebar-accent: oklch(0.274 0.006 286.033);
  --sidebar-accent-fg: oklch(0.985 0 0);
  --sidebar-border: oklch(0.274 0.006 286.033);
  --sidebar-ring: oklch(0.546 0.245 262.881);
}
```

Not sure if it's your style, but it's a great starting point. If you’d like to tweak the colors, check out the [theme customization](/themes) page for more options.

## Intent
The sidebar comes in three variations: `"sidebar"`, `"float"`, and `"inset"`. By default, the variation is set to `"sidebar"`.

### Default
The default variation is a traditional sidebar often used for navigation. <NewTab href='/pre-blocks/sidebar/sidebar-02'/>.
```
<Sidebar intent="default" />
```

### Inset
The inset variation adds padding to the main content for a visually distinct layout. Explore the demo to see it in action, or switch to full-screen mode for a better view. <NewTab href='/pre-blocks/sidebar/sidebar-03'/>.
```
<Sidebar intent="inset" />
```

### Float
The `float` variation introduces an inner border within the sidebar, while the wrapper includes padding around the content. <NewTab href='/pre-blocks/sidebar/sidebar-04'/>
```
<Sidebar intent="float" />
```

## Collapsible
The sidebar can be made collapsible by using the `collapsible` prop in the `SidebarProvider`. The default collapsible behavior is `"hidden"`.

### Hidden
When toggled, the sidebar hides completely from view. <NewTab href='/pre-blocks/sidebar/sidebar-05'/>
```
<Sidebar collapsible="hidden" />
```

### Dock
When toggled, the sidebar docks to a minimal state, showing only icons. Hovering over an icon reveals a tooltip with additional information. <NewTab href='/pre-blocks/sidebar/sidebar-06'/>
```
<Sidebar intent="dock" />
```

## Default Open
The sidebar’s initial state can be controlled using the `defaultOpen` prop. For example, you can set `defaultOpen` to `false` and keep the sidebar docked.
```
<SidebarProvider defaultOpen={false}>
  <Sidebar collapsible="dock" />
```

## Sidebar Section
The sidebar section is a container for sidebar items. It accepts a `label` prop, which will be displayed as a heading.
```
<SidebarSection>
  <SidebarItem isCurrent href="#">
    <SidebarLabel>Item 1</SidebarLabel>
  </SidebarItem>
</SidebarSection>
<SidebarSection label="Other Section">
  <SidebarItem isCurrent href="#">
    <SidebarLabel>Item 1</SidebarLabel>
  </SidebarItem>
</SidebarSection>
```

## Sidebar Disclosure Group
If you need to collapse multiple items, you can use the `SidebarDisclosureGroup` component. <NewTab href='/pre-blocks/sidebar/sidebar-15'/>
```
{sections.map((section, sectionIndex) => (
  <SidebarDisclosureGroup defaultExpandedKeys={[1, 2]} key={sectionIndex}>
    <SidebarDisclosure id={sectionIndex + 1}>
      <SidebarDisclosureTrigger>
        <section.icon />
        <SidebarLabel> {section.label}</SidebarLabel>
      </SidebarDisclosureTrigger>
      <SidebarDisclosurePanel>
        {section.items.map((item, itemIndex) => (
          <SidebarItem key={itemIndex} href="#">
            {({ isHovered }) => (
              <>
                <i aria-hidden className="content-center size-4">
                  <IconBullet className={`${isHovered ? "fill-sky-500 text-sky-500" : ""} size-2 m-auto`} />
                </i>
                <SidebarLabel>{item}</SidebarLabel>
              </>
            )}
          </SidebarItem>
        ))}
      </SidebarDisclosurePanel>
    </SidebarDisclosure>
  </SidebarDisclosureGroup>
))}

const sections = [
  {
    icon: IconNotes,
    label: "Blog",
    items: ["Articles", "Categories", "Tags", "Comments", "Authors"]
  },
  {
    icon: IconStore,
    label: "Commerce",
    items: ["Orders", "Products", "Customers", "Coupons", "Discounts"]
  },
  {
    icon: IconWhiteboard,
    label: "Analytics",
    items: ["Reports", "Traffic", "Conversions", "Audience", "Engagement"]
  },
  {
    icon: IconSettings,
    label: "Settings",
    items: ["General", "Profile", "Billing", "Notifications", "Integrations"]
  }
]
```

## Menu actions
The sidebar supports menus for displaying additional actions or options. When using a menu, be sure to include `data-slot="menu-action-trigger"`.
```
<SidebarItem tooltip="Orders">
  {({ isCollapsed, isFocused }) => (
    <>
      <SidebarLink href="#">
        <SidebarLabel>Orders</SidebarLabel>
      </SidebarLink>
      {(!isCollapsed || isFocused) && (
        <Menu>
          <SidebarMenuTrigger aria-label="Manage">
            <EllipsisHorizontalIcon />
          </MenuTrigger>
          <MenuContent popover={{ offset: 0, placement: "right top" }}>
            <MenuItem href="#new-order">
              <PlusIcon />
              Create New Order
            </MenuItem>
            <MenuItem href="#view-all">
              View All Orders
            </MenuItem>
            <MenuItem href="#pending-orders">
              Pending Orders
            </MenuItem>
            <MenuItem href="#completed-orders">
              Completed Orders
            </MenuItem>
            <MenuItem href="#export-orders">
              Export Orders
            </MenuItem>
          </MenuContent>
        </Menu>
      )}
    </>
  )}
</SidebarItem>
```
<Sandbox
  registries={[
    "sidebar-08",
  ]}
/>

By default, the sidebar menu trigger will be visible when you hover over the sidebar item. If you want to always show the menu trigger, you can use the `alwaysVisible` prop.
```
<SidebarMenuTrigger alwaysVisible aria-label="Manage">
  <EllipsisHorizontalIcon />
</SidebarMenuTrigger>
```


## Badge
The sidebar supports badges, which can be used to indicate the number of unread messages, tasks, or other items. <NewTab href='/pre-blocks/sidebar/sidebar-09'/>
```
<SidebarSection>
  {navigation.map((item, index) => (
    <SidebarItem key={index} isCurrent={item.isCurrent} href="#" badge={item?.badge}>
      {item.icon}
      <SidebarLabel>{item.label}</SidebarLabel>
    </SidebarItem>
  ))}
</SidebarSection>

const navigation = [
  { label: "Overview", icon: <HomeIcon />, isCurrent: true, badge: undefined },
  { label: "Products", icon: <CubeIcon />, isCurrent: false, badge: "31.51K" },
]
```

## Separator
The sidebar supports separators, which can be used to separate sections or groups of items. <NewTab href='/pre-blocks/sidebar/sidebar-19'/>
```tsx {3,6, 9}
<SidebarContent>
  <SidebarSection/>
  <SidebarSeparator />
  <SidebarSection/>
  <SidebarSection/>
  <SidebarSeparator />
  <SidebarSectionGroup/>
  <SidebarSectionGroup/>
  <SidebarSeparator />
  <SidebarSectionGroup/>
</SidebarContent>
```
The example previews will appear similar to the ones in the YouTube sidebar.
<EditorText
  source={{
    'app-sidebar.tsx': 'pre-blocks/sidebar/sidebar-19/app-sidebar',
    'app-sidebar-nav.tsx': 'pre-blocks/sidebar/sidebar-19/app-sidebar-nav',
    'layout.tsx': 'pre-blocks/sidebar/sidebar-19/layout',
    'page.tsx': 'pre-blocks/sidebar/sidebar-19/page',
  }} />

## Tooltip
The sidebar supports tooltips, which can be used to display additional information when you're on docked mode.
<Sandbox
  registries={[
    "sidebar-12",
  ]}
/>

## Header
The sidebar supports headers, which can be used to display additional actions or options.
```
<Sidebar {...props}>
  <SidebarHeader>
    <Link
      className="flex items-center group-data-[collapsible=dock]:size-10 group-data-[collapsible=dock]:justify-center gap-x-2"
      href="/docs/components/layouts/sidebar"
    >
      <SidebarLabel className="font-medium">Intent UI</SidebarLabel>
    </Link>
  </SidebarHeader>
  ...
</Sidebar>
```

## Footer
The sidebar supports footers, which can be used to display additional actions or options.
```
<Sidebar {...props}>
  ...
  <SidebarFooter>
    <Menu>
      <MenuTrigger aria-label="Profile">
        <Avatar isSquare src="https://intentui.com/images/avatar/cobain.jpg" />
        <div className="group-data-[collapsible=dock]:hidden text-sm">
          Kurt Cobain
          <span className="block -mt-0.5 text-muted-fg">kurt@cobain.com</span>
        </div>
        <ChevronDownIcon className="absolute right-3 transition-transform size-4 group-pressed:rotate-180" />
      </MenuTrigger>
      <MenuContent placement="bottom right" className="min-w-(--trigger-width)">
        <MenuItem/>
      </MenuContent>
    </Menu>
  </SidebarFooter>
</Sidebar>
```
## Side
The sidebar has two sides, left and right. You can set the side of the sidebar by using the `side` prop. <NewTab href='/pre-blocks/sidebar/sidebar-16'/>
```
<Sidebar side='left | right'/>
```
<EditorText
  source={{
    'app-sidebar.tsx': 'pre-blocks/sidebar/app-sidebar',
    'app-sidebar-nav.tsx': 'pre-blocks/sidebar/app-sidebar-nav',
    'layout.tsx': 'pre-blocks/sidebar/sidebar-16/layout',
    'page.tsx': 'pre-blocks/sidebar/sidebar-16/page',
  }} />

## Put Anything
You can put anything you want in it. You can use the `SidebarContent` component to wrap your content. Let's try to add a range-calendar and search-field to the sidebar. <NewTab href='/pre-blocks/sidebar/sidebar-17'/>
<EditorText
  source={{
    'app-sidebar.tsx': 'pre-blocks/sidebar/sidebar-17/app-sidebar',
    'layout.tsx': 'pre-blocks/sidebar/sidebar-17/layout',
  }} />

## Remember state
To persist the sidebar’s state across sessions, wrap your layout with the SidebarProvider component. It stores the sidebar’s state in a cookie and restores it when the user revisits the page.
```
import { cookies } from "next/headers"

export default async function Layout({ children }: Readonly<{ children: React.ReactNode }>) {
  const cookieStore = await cookies()
  const sidebarState = cookieStore.get("sidebar_state")

  let defaultOpen = true
  if (sidebarState) {
    defaultOpen = sidebarState.value === "true"
  }
  return (
    <SidebarProvider defaultOpen={defaultOpen}>
```

## Props
The sidebar supports the following props:
### Sidebar
| **Property**  | **Type**                          | **Default** |
|---------------|-----------------------------------|-------------|
| `intent`      | `"default" \| "float" \| "inset"` | `"default"` |
| `collapsible` | `"hidden" \| "dock" \| "none"`    | `"hidden"`  |
| `side`        | `"left" \| "right"`               | `"left"`    |
| `closeButton` | `boolean`                         | `"true"`    |

### SidebarContextProps

| **Property**        | **Type**                    |
|---------------------|-----------------------------|
| `state`             | `"expanded" \| "collapsed"` |
| `open`              | `boolean`                   |
| `setOpen`           | `(open: boolean) => void`   |
| `isOpenOnMobile`    | `boolean`                   |
| `setIsOpenOnMobile` | `(open: boolean) => void`   |
| `isMobile`          | `boolean`                   |
| `toggleSidebar`     | `() => void`                |

### SidebarProviderProps

| **Property**   | **Type**                  | **Default** |
|----------------|---------------------------|-------------|
| `defaultOpen`  | `boolean`                 | `true`      |
| `isOpen`       | `boolean`                 | `undefined` |
| `onOpenChange` | `(open: boolean) => void` | `undefined` |
| `shortcut`     | string                    | `"b"`       |
